package xj.graph2d.tools;

import java.awt.Point;
import java.awt.event.InputEvent;
import java.util.Observer;

import xj.app.DrawTool;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeConstants;

public class MultiPointTool extends SimpleDrawTool {

  public MultiPointTool() {
    this(null, null);
  }

  public MultiPointTool(PointTool pointTool, SelectionTool selTool) {
    if (pointTool != null) {
      this.pointTool = pointTool;
    } else {
      this.pointTool = new PointTool();
    }
    if (selTool != null) {
      this.selTool = selTool;
    } else {
      this.selTool = new SelectionTool();
    }
    this.textTool = new TextTool(DrawShapeConstants.CLONE_PROTOTYPE_DRAW_ATTR);
    this.pointTool.setTextTool(textTool);
  }

  @Override
  public void mouseLButtonPressed(Observer observer, Point p, int modifiers) {
    if (debug) {
      System.out.println("MultiPointTool.mouseLButtonPressed()");
    }

    if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
      // delegate to the selection tool
      if (debug) {
	System.out.println("MultiPointTool.mouseLButtonPressed() + shift");
      }

      if ((modifiers & InputEvent.CTRL_DOWN_MASK) == 0) {
	inSelection = true;
	selTool.mouseLButtonPressed(observer, p, modifiers);
      } else {
	// } else if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
	// delegate to the last insertion tool, for inserting multiple
	// instances of the same shape
	if (debug) {
	  System.out.println("MultiPointTool.mouseLButtonPressed() + ctrl + shift");
	}

	start(observer);
	if (view != null) {
	  DrawTool tool = view.getLastTool();
	  if (tool != null && tool != this) {
	    lastTool = tool;
	  } else {
	    tool = lastTool;
	  }
	  if (tool != null && tool != this) {
	    tool.mouseLButtonPressed(observer, p, modifiers);
	  }
	}

	/*
         * if (lastTool != null && lastTool != this) {
         * lastTool.mouseLButtonPressed(observer, p, modifiers); }
         */

      }
    } else {
      // delegate to the point tool
      pointTool.mouseLButtonPressed(observer, p, modifiers);
    }
  }

  @Override
  public void mouseDragged(Observer observer, Point p, int modifiers) {
    if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
      if ((modifiers & InputEvent.CTRL_DOWN_MASK) == 0) {
	// delegate to the selection tool
	if (!inSelection) {
	  pointTool.mouseDragged(observer, p, modifiers);
	}
      } else {

	// delegate to the last insertion tool, for inserting multiple
	// instances of the same shape
	if (lastTool != null && lastTool != this) {
	  lastTool.mouseDragged(observer, p, modifiers);
	}
      }
    } else {
      // delegate to the point tool
      pointTool.mouseDragged(observer, p, modifiers);
    }
  }

  @Override
  public void mouseLButtonReleased(Observer observer, Point p, int modifiers) {
    if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) {
      if ((modifiers & InputEvent.CTRL_DOWN_MASK) == 0) {
	// delegate to the selection tool
	if (!inSelection) {
	  pointTool.mouseLButtonReleased(observer, p, modifiers);
	}
	inSelection = false;
      } else {
	// } else if ((modifiers & InputEvent.ALT_DOWN_MASK) != 0 ) {
	// delegate to the last insertion tool, for inserting multiple
	// instances of the same shape
	if (lastTool != null && lastTool != this) {
	  lastTool.mouseLButtonReleased(observer, p, modifiers);
	}
      }
    } else {
      // delegate to the point tool
      pointTool.mouseLButtonReleased(observer, p, modifiers);
    }
  }

  @Override
  public void mouseMoved(Observer observer, Point p, int modifiers) {
    if ((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0 && 
	(modifiers & InputEvent.CTRL_DOWN_MASK) != 0) {
      start(observer);
      if (view != null) {
	DrawTool tool = view.getLastTool();
	if (tool != null && tool != this) {
	  lastTool = tool;
	} else {
	  tool = lastTool;
	}
	if (tool != null && tool != this) {
	  if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) {
	    // handle Mac drag with shift+ctrl
	    tool.mouseDragged(observer, p, modifiers);
	  } else {
	    tool.mouseMoved(observer, p, modifiers);
	  }
	}
	ctrlShiftDown = true;
      }
    } else {
      if (!inSelection && ctrlShiftDown) {
	if (view != null) {
	  DrawTool tool = view.getLastTool();
	  if (tool != null && tool != this) {
	    lastTool = tool;
	  } else {
	    tool = lastTool;
	  }
	  if (tool != null && tool != this) {
	    tool.mouseExited(observer, p, modifiers);
	  }
	}
      }
      pointTool.mouseMoved(observer, p, modifiers);
      ctrlShiftDown = false;
    }
  }

  @Override
  public void mouseLButtonDoubleClicked(Observer observer, Point p, int modifiers) {
    pointTool.mouseLButtonDoubleClicked(observer, p, modifiers);
  }

  @Override
  public void mouseRButtonDoubleClicked(Observer observer, Point p, int modifiers) {
    pointTool.mouseRButtonDoubleClicked(observer, p, modifiers);
  }

  @Override
  public void mouseRButtonPressed(Observer observer, Point p, int modifiers) {
    pointTool.mouseRButtonPressed(observer, p, modifiers);
  }

  @Override
  public void mouseRButtonReleased(Observer observer, Point p, int modifiers) {
    pointTool.mouseRButtonReleased(observer, p, modifiers);
  }

  @Override
  public void popupTriggered(Observer observer, Point p, int modifiers) {
    pointTool.popupTriggered(observer, p, modifiers);
  }

  @Override
  public void mouseEntered(Observer observer, Point p, int modifiers) {
    if (!inSelection) {
      pointTool.mouseEntered(observer, p, modifiers);
    }
  }

  @Override
  public void mouseExited(Observer observer, Point p, int modifiers) {
    if (!inSelection) {
      pointTool.mouseExited(observer, p, modifiers);
    }
  }

  @Override
  public void keyPressed(Observer observer, int keyChar, int keyCode,
			 int modifiers) {
    if (!inSelection) {
      pointTool.keyPressed(observer, keyChar, keyCode, modifiers);
    }
  }

  @Override
  public void setActionShape(DrawShape shape) {
    //System.out.println("MultiPointTool.setActionShape() shape == null " + (shape == null));
    actionShape = shape;
    if (!inSelection) { 
      pointTool.setActionShape(shape);
    }
  }

  public PointTool getPointTool() {
    return pointTool;
  }

  protected PointTool pointTool;

  protected SelectionTool selTool;

  protected TextTool textTool;

  protected boolean inSelection = false;

  protected boolean ctrlShiftDown = false;

  protected DrawTool lastTool = null;

  protected static final boolean debug = false;

}
